home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / fs / syms.c < prev    next >
C/C++ Source or Header  |  1995-03-23  |  41KB  |  1,367 lines

  1.  
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified by Morten Welinder, terra@diku.dk, for use with full screen
  16.    debugger.  These changes are copyright 1994 by Morten Welinder.  */
  17. /* Modified by Long Doan, ld@netrix.com, to reduce memory usage.
  18.    These changes are copyrighted 1994-1995 by Long Doan.            */
  19.  
  20. #include <stdio.h>
  21. #include <fcntl.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. #include <dos.h>
  26. #include <sys/stat.h>
  27.  
  28. #include "ed.h"
  29. #include "coff.h"
  30. #include "syms.h"
  31. #include "stab.h"
  32. #include "wild.h"
  33.  
  34. /* END_OF_INCLUDES */
  35.  
  36. #define DO_SYMS 1
  37. #define SYM_FILE_VERSION 0x00010005
  38.  
  39. int undefined_symbol=0;
  40.  
  41. #define Ofs(n) ((int)&(((TSS *)0)->n))
  42.  
  43. struct {
  44.   char *name;
  45.   int size;
  46.   int ofs;
  47. } regs[] = {
  48.   {"%eip"   , 4, Ofs(tss_eip)   },
  49.   {"%eflags", 4, Ofs(tss_eflags)},
  50.   {"%eax"   , 4, Ofs(tss_eax)   },
  51.   {"%ebx"   , 4, Ofs(tss_ebx)   },
  52.   {"%ecx"   , 4, Ofs(tss_ecx)   },
  53.   {"%edx"   , 4, Ofs(tss_edx)   },
  54.   {"%esp"   , 4, Ofs(tss_esp)   },
  55.   {"%ebp"   , 4, Ofs(tss_ebp)   },
  56.   {"%esi"   , 4, Ofs(tss_esi)   },
  57.   {"%edi"   , 4, Ofs(tss_edi)   },
  58.   {"%ax"    , 2, Ofs(tss_eax)   },
  59.   {"%bx"    , 2, Ofs(tss_ebx)   },
  60.   {"%cx"    , 2, Ofs(tss_ecx)   },
  61.   {"%dx"    , 2, Ofs(tss_edx)   },
  62.   {"%ah"    , 1, Ofs(tss_eax)+1 },
  63.   {"%bh"    , 1, Ofs(tss_ebx)+1 },
  64.   {"%ch"    , 1, Ofs(tss_ecx)+1 },
  65.   {"%dh"    , 1, Ofs(tss_edx)+1 },
  66.   {"%al"    , 1, Ofs(tss_eax)   },
  67.   {"%bl"    , 1, Ofs(tss_ebx)   },
  68.   {"%cl"    , 1, Ofs(tss_ecx)   },
  69.   {"%dl"    , 1, Ofs(tss_edx)   },
  70.   {0        , 0, 0              }
  71. };
  72.  
  73. #if !DO_SYMS
  74.  
  75. void syms_init(char *fname) {}
  76. void syms_list(int byval) {}
  77. void syms_listwild(char *pattern) {}
  78.  
  79. word32 syms_name2val(char *name)
  80. {
  81.   if (isdigit(name[0]))
  82.   {
  83.     int v;
  84.     if (strncmp(name, "0x", 2) == 0)
  85.       sscanf(name+2, "%x", &v);
  86.     else
  87.       sscanf(name, "%d", &v);
  88.     undefined_symbol = 0;
  89.     return v;
  90.   }
  91.   else
  92.   {
  93.     undefined_symbol = 1;
  94.     return 0;
  95.   }
  96. }
  97.  
  98. char *syms_val2name(word32 val, word32 *delta)
  99. {
  100.   static char noname_buf[20];
  101.   sprintf(noname_buf, "%#lx", val);
  102.   *delta = 0;
  103.   return noname_buf;
  104. }
  105.  
  106. char *syms_val2line(word32 val, int *lineret, int exact)
  107. {
  108.   return 0;
  109. }
  110.  
  111. char *get_module(int count);
  112. {
  113.   static char noname_buf[20];
  114.   sprintf(noname_buf, "%s", "Why call me here?");
  115.   return noname_buf;
  116. }
  117.  
  118. word32 get_linenum(int filenum, int linenum);
  119. {
  120.   return 0;
  121. }
  122.  
  123. #else
  124.  
  125. /* From the file */
  126.  
  127. typedef struct SYM_ENTRY {
  128.   word32 string_off;
  129.   word8 type;
  130.   word8 other;
  131.   word16 desc;
  132.   word32 val;
  133. } SYM_ENTRY;
  134.  
  135. static FILHDR f_fh;
  136. static AOUTHDR f_ah;
  137. static SCNHDR *f_sh = NULL;
  138. static SYMENT *f_symtab = NULL;
  139. static SYM_ENTRY *f_aoutsyms = NULL;
  140. static AUXENT *f_aux = NULL;
  141. static LINENO **f_lnno = NULL;
  142. static char *f_string_table = NULL;
  143. static char *f_types = NULL;
  144.  
  145. /* built internally */
  146.  
  147. typedef struct {
  148.   char *filename;
  149.   word32 first_address;
  150.   word32 last_address;
  151.   LINENO *lines;
  152.   int num_lines;
  153. } FileNode;
  154.  
  155. static FileNode *files;
  156. static int num_files;
  157.  
  158. typedef struct SymNode {
  159.   char *name;
  160.   word32 address;
  161.   char type_c;
  162. } SymNode;                   
  163.  
  164. typedef struct SymAddr {
  165.   char *name;
  166.   word32 address;
  167.   char type_c;
  168.   word32 range;
  169. } SymAddr;
  170. /* -----------------------------------------------------------------
  171.    - Structures used to dump/read symbols to/from a file.
  172.    ----------------------------------------------------------------- */
  173. typedef struct SymFileHeader {                                         
  174.   word32 version;
  175.   word32 syms_num;
  176.   word32 syms_size;
  177.   word32 file_time;
  178.   word32 files_num;
  179.   word32 start_file;
  180.   word32 file_size;
  181. } SymFileHeader;   
  182.  
  183. typedef struct SymFileEntry {
  184.   word32 offset;
  185. } SymFileEntry;             
  186.  
  187. typedef struct HiloName {
  188.   char *name;
  189.   int  index;
  190. } HiloName;
  191.  
  192. typedef struct HiloAddr {
  193.   word32 addr;
  194.   int    index;
  195. } HiloAddr;
  196. /* -----------------------------------------------------------------
  197.    - Structures used to dump/read line numbers to/from a file.
  198.    ----------------------------------------------------------------- */
  199. typedef struct FileFileEntry {                                         
  200.   char name[100];
  201.   word32 lines_num; 
  202.   word32 first_addr;
  203.   word32 last_addr;
  204.   word32 start_line;
  205. } FileFileEntry;
  206.  
  207. typedef struct LineInfo {
  208.   word32 addr;
  209.   word32 l_no;
  210.   word32 range;
  211. } LineInfo;
  212.  
  213. typedef struct CacheInfo {
  214.   word32 b_addr;
  215.   word32 e_addr;
  216.   int cached_files;
  217.   int *files_cached;
  218.   word32 *begin;
  219.   word32 *end;
  220. } CacheInfo;
  221. /* -----------------------------------------------------------------
  222.    - Original variables used to store symbols.
  223.    ----------------------------------------------------------------- */
  224. static SymNode *syms;
  225. static int num_syms;
  226. /* -----------------------------------------------------------------
  227.    - New variables used to store symbols.
  228.    ----------------------------------------------------------------- */
  229. #define SYM_CACHE_SIZE 100
  230. #define LINE_CACHE_SIZE 682
  231. #define LINE_CACHE_SKIP 100
  232. #define MAX_HILO_CACHE 33
  233. static FILE *sym_file;
  234. static SymFileHeader sym_header;
  235. static SymNode name_cache[SYM_CACHE_SIZE];
  236. static word32 name_cached[SYM_CACHE_SIZE];
  237. static SymAddr addr_cache[SYM_CACHE_SIZE];
  238. static HiloName *name_hilo_cache;
  239. static HiloAddr *addr_hilo_cache;
  240. static int name_in_cache = 0;
  241. static int addr_in_cache = 0;
  242. static int entry_to_free = 0;
  243. static int cached_name_end = 0;
  244. static int cached_name_free = 0;
  245. static int hilo_cache_size;
  246. static FileFileEntry *file_entries; 
  247. static LINENO line_cache[LINE_CACHE_SIZE];
  248. static CacheInfo line_cache_info;
  249. static char dos_buffer[4096];
  250. /* -----------------------------------------------------------------
  251.    - Utilities
  252.    ----------------------------------------------------------------- */
  253. static int syms_sort_bn(const void *a, const void *b)
  254. { SymNode *sa = (SymNode *)a;
  255.   SymNode *sb = (SymNode *)b;
  256.   return strcmp(sa->name, sb->name);
  257. }
  258. /* ----------------------------------------------------------------- */
  259. static int syms_sort_bv(const void *a, const void *b)
  260. { SymAddr *sa = (SymAddr *)a;
  261.   SymAddr *sb = (SymAddr *)b;
  262.   return sa->address - sb->address;
  263. }
  264. /* ----------------------------------------------------------------- */
  265. static char *symndup(char *s, int len)
  266. { char c = s[len], *rv;
  267.   s[len] = 0;
  268.   rv = strdup(s);
  269.   s[len] = c;
  270.   return rv;
  271. }
  272. /* ----------------------------------------------------------------- */
  273. static void
  274. get_sym_name_by_num (SymNode *sym, word32 num)
  275. { word32 offset;
  276.   int i;
  277.   SymFileEntry entry;
  278.                     
  279.   if (num >= num_syms)
  280.     return;
  281.   
  282.   for (i = 0; i < cached_name_end; i++)
  283.     if (name_cached[i] == num)
  284.     { sym->address = name_cache[i].address;
  285.       sym->type_c  = name_cache[i].type_c;
  286.       strcpy (sym->name, name_cache[i].name);
  287.       return;
  288.     }
  289.   offset = num * sizeof (SymFileEntry) + sym_header.syms_size;   
  290.   fseek (sym_file, offset, SEEK_SET);
  291.   fread (&entry, sizeof (SymFileEntry) , 1, sym_file);
  292.   fseek (sym_file, entry.offset, SEEK_SET);
  293.   fread (&(sym->address) , sizeof (word32), 1, sym_file);
  294.   fread (&(sym->type_c) , sizeof (char)   , 1, sym_file);
  295.   fgets (sym->name, 150, sym_file);
  296.   sym->name[strlen (sym->name) - 1] = 0;
  297.  
  298.   if (cached_name_end == SYM_CACHE_SIZE)
  299.   { i = cached_name_free;
  300.     cached_name_free++;
  301.     if (cached_name_free == cached_name_end)
  302.       cached_name_free = 0;
  303.   } else
  304.   { i = cached_name_end;
  305.     cached_name_end++;   
  306.     name_cache[i].name = malloc (151);
  307.   }
  308.   name_cache[i].address = sym->address;
  309.   name_cache[i].type_c  = sym->type_c;
  310.   strcpy (name_cache[i].name, sym->name);
  311.   name_cached[i] = num;
  312. }
  313. /* ----------------------------------------------------------------- */
  314. static void
  315. get_sym_addr_by_num (SymNode *sym, word32 num)
  316. { word32 offset;
  317.   SymFileEntry entry;
  318.                     
  319.   if (num >= num_syms)
  320.     return;
  321.   offset = (num + num_syms) * sizeof (SymFileEntry) + sym_header.syms_size;   
  322.   fseek (sym_file, offset, SEEK_SET);
  323.   fread (&entry, sizeof (SymFileEntry) , 1, sym_file);
  324.   fseek (sym_file, entry.offset, SEEK_SET);
  325.   fread (&(sym->address) , sizeof (word32)   , 1, sym_file);
  326.   fread (&(sym->type_c) , sizeof (char)   , 1, sym_file);
  327.   fgets (sym->name, 150, sym_file);
  328.   sym->name[strlen (sym->name) - 1] = 0;
  329. }
  330. /* ----------------------------------------------------------------- */
  331. static void
  332. init_cache (void)
  333. { int hi, lo, count, c_hi, c_lo, interval;
  334.   char temp[151];
  335.   SymNode sym;              
  336.  
  337.   for (hilo_cache_size = MAX_HILO_CACHE; hilo_cache_size > num_syms;
  338.        hilo_cache_size--)
  339.     ;
  340.   if (!(hilo_cache_size % 2))
  341.     hilo_cache_size--;
  342.   if (hilo_cache_size == 1)
  343.     hilo_cache_size = 0;
  344.   if (hilo_cache_size <= 0)
  345.   { hilo_cache_size = 0;
  346.     return;
  347.   }
  348.   name_hilo_cache = malloc (hilo_cache_size * sizeof (HiloName));
  349.   addr_hilo_cache = malloc (hilo_cache_size * sizeof (HiloAddr));
  350.   count = hilo_cache_size;
  351.   hi = num_syms - 1;
  352.   lo = 0;                                     
  353.   interval = num_syms / (hilo_cache_size - 1);
  354.   c_hi = hilo_cache_size - 1;
  355.   c_lo = 0;
  356.   sym.name = temp;
  357.   while (count > 1)
  358.   { get_sym_name_by_num (&sym, lo);
  359.     name_hilo_cache[c_lo].name  = strdup (sym.name);
  360.     name_hilo_cache[c_lo].index = lo;
  361.     get_sym_name_by_num (&sym, hi);
  362.     name_hilo_cache[c_hi].name  = strdup (sym.name);
  363.     name_hilo_cache[c_hi].index = hi;
  364.     get_sym_addr_by_num (&sym, lo);
  365.     addr_hilo_cache[c_lo].addr  = sym.address;
  366.     addr_hilo_cache[c_lo].index = lo;
  367.     get_sym_addr_by_num (&sym, hi);
  368.     addr_hilo_cache[c_hi].addr  = sym.address;
  369.     addr_hilo_cache[c_hi].index = hi;
  370.     count -= 2;
  371.     hi -= interval;
  372.     lo += interval;                          
  373.     if (lo > hi)
  374.       lo = hi;
  375.     c_hi--;
  376.     c_lo++;
  377.   }
  378.   get_sym_name_by_num (&sym, lo);
  379.   name_hilo_cache[c_lo].name  = strdup (sym.name);
  380.   name_hilo_cache[c_lo].index = lo;
  381.   sym.name = temp;
  382.   get_sym_addr_by_num (&sym, lo);
  383.   addr_hilo_cache[c_lo].addr  = sym.address;
  384.   addr_hilo_cache[c_lo].index = lo;
  385.  
  386.   line_cache_info.cached_files = 0;
  387.   line_cache_info.files_cached = malloc (sizeof (int));
  388.   line_cache_info.begin = malloc (sizeof (word32));
  389.   line_cache_info.end = malloc (sizeof (word32));
  390. }
  391. /* ----------------------------------------------------------------- */
  392. static void
  393. get_name_hilo (char *name, int *hi, int *lo)
  394. { int c_hi, c_lo;
  395.   if (!hilo_cache_size)
  396.   { *hi = -1;
  397.     *lo = -1;
  398.     return;
  399.   }
  400.   c_hi = hilo_cache_size - 1;
  401.   c_lo = 0;                       
  402.   while ((c_hi >= 0) && (strcmp (name, name_hilo_cache[c_hi].name) <= 0))
  403.     c_hi--;                                                                 
  404.   if (c_hi < hilo_cache_size - 1)
  405.     c_hi++;
  406.   while ((c_lo <= c_hi) && (strcmp (name, name_hilo_cache[c_lo].name) >= 0))
  407.     c_lo++;
  408.   if (c_lo > 0)
  409.     c_lo--;
  410.   *hi = name_hilo_cache[c_hi].index;
  411.   *lo = name_hilo_cache[c_lo].index;      
  412. }
  413. /* ----------------------------------------------------------------- */
  414. static void
  415. get_addr_hilo (word32 addr, int *hi, int *lo)
  416. { int c_hi, c_lo;
  417.   if (!hilo_cache_size)
  418.   { *hi = -1;
  419.     *lo = -1;
  420.     return;
  421.   }
  422.   c_hi = hilo_cache_size - 1;
  423.   c_lo = 0;
  424.   if (addr > addr_hilo_cache[c_hi].addr ||
  425.       addr < addr_hilo_cache[c_lo].addr)
  426.   { *hi = -1;
  427.     *lo = -1;
  428.     return;
  429.   }
  430.   while ((c_hi >= 0) && (addr <= addr_hilo_cache[c_hi].addr))
  431.     c_hi--;                                                                 
  432.   if (c_hi < hilo_cache_size - 1)
  433.     c_hi++;
  434.   while ((c_lo <= c_hi) && (addr >= addr_hilo_cache[c_lo].addr))
  435.     c_lo++;
  436.   if (c_lo > 0)
  437.     c_lo--;
  438.   *hi = addr_hilo_cache[c_hi].index;
  439.   *lo = addr_hilo_cache[c_lo].index;
  440. }
  441. /* ----------------------------------------------------------------- */
  442. static int valid_symbol(int i)
  443. { char *sn;
  444.   if (f_symtab[i].e.e.e_zeroes)
  445.     sn = f_symtab[i].e.e_name; 
  446.   else
  447.     sn = f_string_table + f_symtab[i].e.e.e_offset;
  448.   if (sn[0] != '_')
  449.     return 0;
  450.   if (strncmp(sn, "___gnu_compiled", 15) == 0)
  451.     return 0;
  452.   if (strcmp(sn, "__DYNAMIC") == 0)
  453.     return 0;
  454.   return 1;
  455. }
  456. /* ----------------------------------------------------------------- */
  457. static void process_coff(FILE *fd, long ofs)
  458. { int i, f, s, f_pending;
  459.   LINENO *l = 0;
  460.   int l_pending;
  461.   word32 strsize;
  462.   char *name;
  463.  
  464.   fseek(fd, ofs, 0);
  465.   fread(&f_fh, 1, FILHSZ, fd);
  466.   fread(&f_ah, 1, AOUTSZ, fd);
  467.   f_sh = (SCNHDR *)malloc(f_fh.f_nscns * SCNHSZ);
  468.   f_types = (char *)malloc(f_fh.f_nscns);
  469.   f_lnno = (LINENO **)malloc(f_fh.f_nscns * sizeof(LINENO *));
  470.   fread(f_sh, f_fh.f_nscns, SCNHSZ, fd);
  471.  
  472.   for (i=0; i<f_fh.f_nscns; i++)
  473.   { if (f_sh[i].s_flags & STYP_TEXT)
  474.       f_types[i] = 'T';
  475.     if (f_sh[i].s_flags & STYP_DATA)
  476.       f_types[i] = 'D';
  477.     if (f_sh[i].s_flags & STYP_BSS)
  478.       f_types[i] = 'B';
  479.     if (f_sh[i].s_nlnno)
  480.     { fseek(fd, ofs + f_sh[i].s_lnnoptr, 0L);
  481.       f_lnno[i] = (LINENO *)malloc(f_sh[i].s_nlnno * LINESZ);
  482.       fread(f_lnno[i], LINESZ, f_sh[i].s_nlnno, fd);
  483.     } else
  484.       f_lnno[i] = 0;
  485.   }
  486.  
  487.   fseek(fd, ofs + f_fh.f_symptr + f_fh.f_nsyms * SYMESZ, 0);
  488.   fread(&strsize, 1, 4, fd);
  489.   f_string_table = (char *)malloc(strsize);
  490.   fread(f_string_table+4, 1, strsize-4, fd);
  491.   f_string_table[0] = 0;
  492.  
  493.   fseek(fd, ofs+f_fh.f_symptr, 0);
  494.   f_symtab = (SYMENT *)malloc(f_fh.f_nsyms * SYMESZ);
  495.   fread(f_symtab, SYMESZ, f_fh.f_nsyms, fd);
  496.   f_aux = (AUXENT *)f_symtab;
  497.  
  498.   num_syms = num_files = 0;
  499.   for (i=0; i<f_fh.f_nsyms; i++)
  500.   { switch (f_symtab[i].e_sclass)
  501.     { case C_FILE:
  502.     num_files++;
  503.     break;
  504.       case C_EXT:
  505.       case C_STAT:
  506.     if (!valid_symbol(i))
  507.       break;
  508.     num_syms++;
  509.     break;
  510.     }
  511.     i += f_symtab[i].e_numaux;
  512.   }
  513.  
  514.   files = (FileNode *)malloc(num_files * sizeof(FileNode));
  515.  
  516.   syms = (SymNode *)malloc(num_syms * sizeof(SymNode));
  517.  
  518.   f = s = f_pending = l_pending = 0;
  519.   for (i=0; i<f_fh.f_nsyms; i++)
  520.   { switch (f_symtab[i].e_sclass)
  521.     { case C_FILE:
  522.     if (f_aux[i+1].x_file.x_n.x_zeroes)
  523. /* -----------------------------------------------------------------
  524.    - This will return in a lost of 16 bytes in memory when the name is freed.
  525.    ----------------------------------------------------------------- */
  526.       files[f].filename = symndup(f_aux[i+1].x_file.x_fname, 16);
  527.     else
  528.       files[f].filename = f_string_table + f_aux[i+1].x_file.x_n.x_offset;
  529.     files[f].lines = 0;
  530.     f_pending = 1;
  531.     f++;
  532.     break;
  533.       case C_EXT:
  534.       case C_STAT:
  535.     if (f_symtab[i].e.e.e_zeroes)
  536.       name = f_symtab[i].e.e_name;
  537.     else
  538.       name = f_string_table + f_symtab[i].e.e.e_offset;
  539.     if (f_pending && strcmp(name, ".text") == 0)
  540.     { files[f-1].first_address = f_symtab[i].e_value;
  541.       files[f-1].last_address = f_symtab[i].e_value + f_aux[i+1].x_scn.x_scnlen - 1;
  542.       files[f-1].num_lines = f_aux[i+1].x_scn.x_nlinno;
  543.       f_pending = 0;
  544.     }
  545.     if (ISFCN(f_symtab[i].e_type))
  546.     { int scn = f_symtab[i].e_scnum - 1;
  547.       l = f_lnno[scn] + ((f_aux[i+1].x_sym.x_fcnary.x_fcn.x_lnnoptr - f_sh[scn].s_lnnoptr)/LINESZ);
  548.       l_pending = 1;
  549.       l->l_addr.l_paddr = f_symtab[i].e_value;
  550.     }
  551.     if (!valid_symbol(i))
  552.       break;
  553.     syms[s].address = f_symtab[i].e_value;
  554.     if (f_symtab[i].e.e.e_zeroes)
  555. /* -----------------------------------------------------------------
  556.    - This will return in a lost of 8 bytes in memory when the name is freed.
  557.    ----------------------------------------------------------------- */
  558.       syms[s].name = symndup(f_symtab[i].e.e_name, 8);
  559.     else
  560.       syms[s].name = f_string_table + f_symtab[i].e.e.e_offset;
  561.     switch (f_symtab[i].e_scnum)
  562.     { case 1 ... 10:
  563.         syms[s].type_c = f_types[f_symtab[i].e_scnum-1];
  564.         break;
  565.       case N_UNDEF:
  566.         syms[s].type_c = 'U';
  567.         break;
  568.       case N_ABS:
  569.         syms[s].type_c = 'A';
  570.         break;
  571.       case N_DEBUG:
  572.         syms[s].type_c = 'D';
  573.         break;
  574.     }
  575.     if (f_symtab[i].e_sclass == C_STAT)
  576.       syms[s].type_c += 'a' - 'A';
  577.  
  578.     s++;
  579.     break;
  580.       case C_FCN:
  581.     if (f_pending && files[f-1].lines == 0)
  582.     { files[f-1].lines = l;
  583.     }
  584.     if (l_pending)
  585.     { int lbase = f_aux[i+1].x_sym.x_misc.x_lnsz.x_lnno - 1;
  586.       int i2;
  587.       l->l_lnno = lbase;
  588.       l++;
  589.       for (i2=0; l[i2].l_lnno; i2++)
  590.         l[i2].l_lnno += lbase;
  591.       l_pending = 0;
  592.     }
  593.     break;
  594.     }
  595.     i += f_symtab[i].e_numaux;
  596.   }
  597. }
  598. /* ----------------------------------------------------------------- */
  599. static void process_aout(FILE *fd, long ofs)
  600. { GNU_AOUT header;
  601.   word32 string_table_length;
  602.   int nsyms, i, f, s, l;
  603.  
  604.   fseek(fd, ofs, 0);
  605.   fread(&header, 1, sizeof(header), fd);
  606.  
  607.   fseek(fd, ofs + sizeof(header) + header.tsize + header.dsize + header.txrel + header.dtrel, 0);
  608.   nsyms = header.symsize / sizeof(SYM_ENTRY);
  609.   f_aoutsyms = (SYM_ENTRY *)malloc(header.symsize);
  610.   fread(f_aoutsyms, 1, header.symsize, fd);
  611.  
  612.   fread(&string_table_length, 1, 4, fd);
  613.   f_string_table = (char *)malloc(string_table_length);
  614.   fread(f_string_table+4, 1, string_table_length-4, fd);
  615.   f_string_table[0] = 0;
  616.  
  617.   num_files = num_syms = 0;
  618.   for (i=0; i<nsyms; i++)
  619.   { char *symn = f_string_table + f_aoutsyms[i].string_off;
  620.     char *cp;
  621.     switch (f_aoutsyms[i].type & ~N_EXT)
  622.     { case N_SO:
  623.     if (symn[strlen(symn)-1] == '/')
  624.       break;
  625.     num_files++;
  626.     break;
  627.       case N_TEXT:
  628.     cp = symn + strlen(symn) - 2;
  629.     if (strncmp(symn, "___gnu", 6) == 0 ||
  630.         strcmp(cp, "d.") == 0 /* as in gcc_compiled. */ ||
  631.         strcmp(cp, ".o") == 0)
  632.       break;
  633.       case N_DATA:
  634.       case N_ABS:
  635.       case N_BSS:
  636.       case N_FN:
  637.       case N_SETV:
  638.       case N_SETA:
  639.       case N_SETT:
  640.       case N_SETD:
  641.       case N_SETB:
  642.       case N_INDR:
  643.     num_syms ++;
  644.     break;
  645.     }
  646.   }
  647.  
  648.   syms = (SymNode *)malloc(num_syms * sizeof(SymNode));
  649.   memset(syms, num_syms * sizeof(SymNode), 0);
  650.   files = (FileNode *)malloc(num_files * sizeof(FileNode));
  651.   memset(files, num_files * sizeof(FileNode), 0);
  652.  
  653.   f = s = 0;
  654.   for (i=0; i<nsyms; i++)
  655.   { char c, *cp;
  656.     char *symn = f_string_table + f_aoutsyms[i].string_off;
  657.     switch (f_aoutsyms[i].type & ~N_EXT)
  658.     { case N_SO:
  659.     if (symn[strlen(symn)-1] == '/')
  660.       break;
  661.     if (f && files[f-1].last_address == 0)
  662.       files[f-1].last_address = f_aoutsyms[i].val - 1;
  663.     files[f].filename = symn;
  664.     files[f].first_address = f_aoutsyms[i].val;
  665.     f ++;
  666.     break;
  667.       case N_SLINE:
  668.     files[f-1].num_lines++;
  669.     break;
  670.       case N_TEXT:
  671.     cp = symn + strlen(symn) - 2;
  672.     if (strncmp(symn, "___gnu", 6) == 0 ||
  673.         strcmp(cp, "d.") == 0 /* as in gcc_compiled. */ ||
  674.         strcmp(cp, ".o") == 0)
  675.     { if (f && files[f-1].last_address == 0)
  676.         files[f-1].last_address = f_aoutsyms[i].val - 1;
  677.       break;
  678.     }
  679.     c = 't';
  680.     goto sym_c;
  681.       case N_DATA:
  682.     c = 'd';
  683.     goto sym_c;
  684.       case N_ABS:
  685.     c = 'a';
  686.     goto sym_c;
  687.       case N_BSS:
  688.     c = 'b';
  689.     goto sym_c;
  690.       case N_FN:
  691.     c = 'f';
  692.     goto sym_c;
  693.       case N_SETV:
  694.     c = 'v';
  695.     goto sym_c;
  696.       case N_SETA:
  697.     c = 'v';
  698.     goto sym_c;
  699.       case N_SETT:
  700.     c = 'v';
  701.     goto sym_c;
  702.       case N_SETD:
  703.     c = 'v';
  704.     goto sym_c;
  705.       case N_SETB:
  706.     c = 'v';
  707.     goto sym_c;
  708.       case N_INDR:
  709.     c = 'i';
  710.     sym_c:
  711.     syms[s].name = symn;
  712.     syms[s].address = f_aoutsyms[i].val;
  713.     syms[s].type_c = (f_aoutsyms[i].type & N_EXT) ? (c+'A'-'a') : c;
  714.     s ++;
  715.     break;
  716.     }
  717.   }
  718.   
  719.   l = f = 0;
  720.   for (i=0; i<nsyms; i++)
  721.   { char *symn = f_string_table + f_aoutsyms[i].string_off;
  722.     switch (f_aoutsyms[i].type & ~N_EXT)
  723.     { case N_SO:
  724.     if (symn[strlen(symn)-1] == '/')
  725.       break;
  726.     files[f].lines = (LINENO *)malloc(files[f].num_lines * sizeof(LINENO));
  727.     f++;
  728.     l = 0;
  729.     break;
  730.       case N_SLINE:
  731.     files[f-1].lines[l].l_addr.l_paddr = f_aoutsyms[i].val;
  732.     files[f-1].lines[l].l_lnno = f_aoutsyms[i].desc;
  733.     l ++;
  734.     break;
  735.     }
  736.   }
  737.  
  738. }
  739. /* ----------------------------------------------------------------- */
  740. static void process_file(FILE *fd, long ofs)
  741. { short s, exe[2];
  742.   fseek(fd, ofs, 0);
  743.   fread(&s, 1, 2, fd);
  744.   switch (s)
  745.   { case 0x5a4d:        /* .exe */
  746.       fread(exe, 2, 2, fd);
  747.       ofs += (long)exe[1] * 512L;
  748.       if (exe[0])
  749.     ofs += (long)exe[0] - 512L;
  750.       process_file(fd, ofs);
  751.       break;
  752.     case 0x014c:        /* .coff */
  753.       process_coff(fd, ofs);
  754.       break;
  755.     case 0x010b:        /* a.out ZMAGIC */
  756.     case 0x0107:        /* a.out object */
  757.       process_aout(fd, ofs);
  758.       break;
  759.   }
  760. }
  761. /* -----------------------------------------------------------------
  762.    - Interface fuctions.
  763.    ----------------------------------------------------------------- */
  764. void syms_init(char *fname)
  765. { FILE *fd = fopen(fname, "rb");
  766.   int i, len = strlen (fname);  
  767.   word32 org_time;
  768.   char *symfilename = alloca (len + 4);
  769. /*  struct stat statbuf; */
  770.   int used = 0, left = 4096;  
  771.                
  772.   if (fd == 0)
  773.   { perror(fname);
  774.   } else
  775.   { SymFileEntry *name_entries, *addr_entries;
  776.     word32 sym_offset;
  777.     SymAddr *syms_byaddr;
  778.  
  779.     getftime (fileno (fd), (struct ftime *)&org_time);
  780.     strcpy (symfilename, sympath);
  781.     strcpy (symfilename + strlen (symfilename), symname);
  782.     symfilename[strlen (symfilename) + 1] = 0;
  783.     symfilename[strlen (symfilename)] = '.';
  784.     strcpy (symfilename + strlen (symfilename), symext);
  785. /*    if (stat(symfilename, &statbuf) != -1)  */
  786. /*    if (0 == access (symfilename, 4))       */
  787.       sym_file = fopen (symfilename, "rb");
  788. /*    else
  789.       sym_file = 0;                           */
  790.     if (sym_file)
  791.     { fread (&sym_header, sizeof (SymFileHeader), 1, sym_file);
  792.       if (sym_header.file_time == org_time &&
  793.       sym_header.version == SYM_FILE_VERSION)
  794.       {  num_syms = sym_header.syms_num;
  795.      num_files = sym_header.files_num;
  796.      fseek (sym_file, 0, SEEK_END);
  797.      sym_offset = ftell (sym_file);
  798.      if (sym_offset == sym_header.file_size)
  799.      { printf ("Use symbol file %s\n", symfilename);
  800.        init_cache ();                              
  801.        fseek (sym_file, sym_header.start_file, SEEK_SET);
  802.        file_entries = malloc (num_files * sizeof (FileFileEntry));
  803.        fread (file_entries, sizeof (FileFileEntry), num_files, sym_file);
  804.        return;
  805.      }
  806.       }
  807.       fclose (sym_file);
  808.     } 
  809.     printf ("Create symbol file %s\n", symfilename);
  810.     sym_file = fopen (symfilename, "wb");
  811.     process_file(fd, 0);
  812.     fclose(fd);
  813.     sym_header.version   = SYM_FILE_VERSION;
  814.     sym_header.syms_num  = num_syms;
  815.     sym_header.file_time = org_time;
  816.     sym_header.files_num = num_files;
  817.     fwrite (&sym_header, sizeof (SymFileHeader), 1, sym_file);
  818.     name_entries = (SymFileEntry *)malloc (num_syms * sizeof (SymFileEntry));
  819.     addr_entries = (SymFileEntry *)malloc (num_syms * sizeof (SymFileEntry));
  820. /* -----------------------------------------------------------------
  821.    - Sort the original symbol table by name, and move to file.
  822.    ----------------------------------------------------------------- */
  823.     sym_offset = sizeof (SymFileHeader);
  824.     qsort(syms, num_syms, sizeof(SymNode), syms_sort_bn);
  825.     for (i = 0; i < num_syms; i++)
  826.     { name_entries[i].offset = sym_offset;
  827.       len = strlen (syms[i].name) + 1;
  828.       if (left < 5 + len)
  829.       { fwrite (dos_buffer, 1, used, sym_file);
  830.     used = 0;
  831.     left = 4096;
  832.       }
  833.       *(word32 *)(dos_buffer + used) = syms[i].address;
  834.       *(dos_buffer + used + 4)       = syms[i].type_c;
  835.       strcpy (dos_buffer + used + 5, syms[i].name);
  836.       *(dos_buffer + used + len + 4) = '\n';
  837.       used += len + 5;
  838.       left -= len + 5;
  839.       sym_offset += len + 5;
  840. /*      free (syms[i].name);  */
  841.     }                                     
  842.     if (used)
  843.       fwrite (dos_buffer, 1, used, sym_file);
  844.      
  845.     sym_header.syms_size = sym_offset;
  846. /* -----------------------------------------------------------------
  847.    - Sort the original symbol table by address, and record their offset.
  848.    ----------------------------------------------------------------- */
  849.     syms_byaddr = (SymAddr *)malloc(num_syms * sizeof(SymAddr));
  850.     for (i = 0; i < num_syms; i++)
  851.     { memcpy(&(syms_byaddr[i]), &(syms[i]), sizeof(SymNode));
  852.       syms_byaddr[i].range = i;
  853.     }
  854.     qsort(syms_byaddr, num_syms, sizeof(SymAddr), syms_sort_bv);      
  855.     for (i = 0; i < num_syms; i++)
  856.       addr_entries[i].offset = name_entries[syms_byaddr[i].range].offset;
  857.     free (syms);
  858.     free (syms_byaddr);
  859. /* -----------------------------------------------------------------
  860.    - Write the offset tables to the file and free them.
  861.    ----------------------------------------------------------------- */
  862.     fwrite (name_entries, sizeof (SymFileEntry), num_syms, sym_file);
  863.     fwrite (addr_entries, sizeof (SymFileEntry), num_syms, sym_file);
  864.     free (name_entries);
  865.     free (addr_entries);
  866.     sym_header.start_file = sym_header.syms_size + 
  867.                 2 * num_syms * sizeof (SymFileEntry); 
  868.     sym_header.file_size = sym_header.start_file +
  869.                num_files * sizeof (FileFileEntry);
  870. /* -----------------------------------------------------------------
  871.    - Write the line number information to the file, and free them.
  872.    ----------------------------------------------------------------- */
  873.     file_entries = malloc (num_files * sizeof (FileFileEntry));
  874.     for (i = 0; i < num_files; i++)
  875.     { file_entries[i].lines_num  = files[i].num_lines;
  876.       file_entries[i].start_line = sym_header.file_size;  
  877.       file_entries[i].first_addr = files[i].first_address;
  878.       file_entries[i].last_addr  = files[i].last_address;
  879.       strncpy (file_entries[i].name, files[i].filename, 99);
  880.       sym_header.file_size += files[i].num_lines * LINESZ;
  881.     }                                                     
  882.     fwrite (file_entries, sizeof (FileFileEntry), num_files, sym_file);
  883.     for (i = 0; i < num_files; i++)
  884.     { fwrite (files[i].lines, LINESZ, files[i].num_lines, sym_file);
  885.       free (files[i].lines);                             
  886. /*      free (files[i].filename);  */
  887.     }
  888.     free (files);
  889.  
  890.     free (f_string_table);
  891.     free (f_sh);
  892.     free (f_symtab);
  893.     free (f_aoutsyms);
  894.     free (f_aux);
  895.     free (f_lnno);
  896.     free (f_types);
  897. /* -----------------------------------------------------------------
  898.    - Write the adjusted header to the file.
  899.    ----------------------------------------------------------------- */
  900.     fseek (sym_file, 0, SEEK_SET);
  901.     fwrite (&sym_header, sizeof (SymFileHeader), 1, sym_file);
  902.     fclose (sym_file);
  903. /* -----------------------------------------------------------------
  904.    - Test the intergity of the file.
  905.    ----------------------------------------------------------------- */
  906.     sym_file = fopen (symfilename, "rb");
  907.     fseek (sym_file, 0, SEEK_END);
  908.     sym_offset = ftell (sym_file);                                              
  909.     if (sym_offset != sym_header.file_size)
  910.     { fclose (sym_file);
  911.       perror (symfilename);
  912.     }                          
  913.   }
  914.   init_cache ();
  915. }
  916. /* ----------------------------------------------------------------- */
  917. static void
  918. get_sym_by_name (SymNode *sym, char *name)
  919. { int hi, lo, mid, found = 0;
  920.   int err;
  921.   
  922.   get_name_hilo (name, &hi, &lo);
  923.   if (hi < 0 || lo < 0)
  924.   { sym->name = 0;    
  925.     return;
  926.   } 
  927.   sym->name = malloc (151);
  928.   do
  929.   { mid = (hi + lo) / 2;
  930.     get_sym_name_by_num (sym, mid);
  931.     err = strcmp (name, sym->name);   
  932.     if (err == 0)
  933.       found = 1;
  934.     else if (err < 0)
  935.       hi = mid;
  936.     else
  937.       lo = mid;
  938.     err = (hi - lo <= 1) && !found;
  939.   } while (!found && !err);    
  940.   if (err)
  941.   { free (sym->name);
  942.     sym->name = 0;
  943.   }                                        
  944. }
  945. /* ----------------------------------------------------------------- */
  946. static int
  947. get_sym_by_addr (word32 addr)
  948. { int hi, lo, mid;
  949.   word32 offset, start_offset;
  950.   SymFileEntry entry;
  951.   SymNode sym_n;
  952.             
  953.   if (addr < 0x1000)
  954.     return (-1);
  955.            
  956.   for (mid = 0; mid < addr_in_cache; mid++)
  957.     if (addr_cache[mid].address <= addr && addr <= addr_cache[mid].range)
  958.       return (mid);                        
  959.  
  960.   get_addr_hilo (addr, &hi, &lo);
  961.   if (hi < 0 || lo < 0)
  962.     return (-1);
  963.   sym_n.name = malloc (151);                    
  964.   start_offset = sym_header.syms_size + num_syms * sizeof (SymFileEntry);
  965.   do
  966.   { mid = (hi + lo) / 2;
  967.     get_sym_addr_by_num (&sym_n, mid);
  968.     if (sym_n.address == addr)
  969.       break;
  970.     if (sym_n.address > addr)
  971.       hi = mid;
  972.     else
  973.       lo = mid;
  974.   } while (hi - lo > 1);
  975.  
  976.   if (sym_n.address > addr)
  977.     mid--; /* the last below was it */
  978.   if (mid >= 0)
  979.   { get_sym_addr_by_num (&sym_n, mid);
  980.     offset = (mid + 1) * sizeof (SymFileEntry) + start_offset;   
  981.     fseek (sym_file, offset, SEEK_SET);
  982.     fread (&entry, sizeof (SymFileEntry) , 1, sym_file);
  983.     fseek (sym_file, entry.offset, SEEK_SET);
  984.     fread (&start_offset, sizeof (word32), 1, sym_file);
  985.   } else 
  986.   { free (sym_n.name);
  987.     return (-1);
  988.   } 
  989.  
  990.   if (addr_in_cache == SYM_CACHE_SIZE)
  991.   { free (addr_cache[entry_to_free].name);
  992.     mid = entry_to_free;
  993.     entry_to_free++;
  994.     if (entry_to_free == addr_in_cache)
  995.       entry_to_free = 0;
  996.   } else
  997.   { mid = addr_in_cache;
  998.     addr_in_cache++;
  999.   }
  1000.   addr_cache[mid].name    = sym_n.name;
  1001.   addr_cache[mid].address = sym_n.address;
  1002.   addr_cache[mid].type_c  = sym_n.type_c;
  1003.   addr_cache[mid].range   = start_offset - 1;
  1004.   return (mid);
  1005. }
  1006. /* ----------------------------------------------------------------- */
  1007. static int
  1008. lookup_sym_byname(char *name, int idx, int ofs)
  1009. { SymNode sym;               
  1010.   char temp[151];
  1011.  
  1012.   sprintf (temp, "%s%s", ofs ? "_" : "", name);
  1013.   temp[idx + ofs + 1] = '\0';
  1014.   get_sym_by_name (&sym, temp);
  1015.   if (!(sym.name))
  1016.     return (-1);
  1017.   if (name_in_cache)
  1018.     free (name_cache[0].name);
  1019.   else
  1020.     name_in_cache = 1;        
  1021.   name_cache[0].name    = strdup (sym.name);
  1022.   name_cache[0].address = sym.address;
  1023.   name_cache[0].type_c  = sym.type_c;
  1024.   free (sym.name);
  1025.   return (0);
  1026. }
  1027. /* ----------------------------------------------------------------- */
  1028. static void
  1029. get_line_block (int file, int line, LINENO *l_info)
  1030. { fseek (sym_file, file_entries[file].start_line + line * LINESZ, SEEK_SET);
  1031.   fread (l_info, LINESZ, LINE_CACHE_SIZE, sym_file);
  1032. }
  1033. /* ----------------------------------------------------------------- */
  1034. static void
  1035. do_fill (word32 addr, int file)
  1036. { int start_line = 0, end_line = 0, count;
  1037.   int start_file = file, end_file = file, total_lines;
  1038.  
  1039.   do {
  1040.     start_line = end_line;
  1041.     get_line_block (file, start_line, line_cache);
  1042.     end_line = start_line + LINE_CACHE_SIZE;
  1043.     if (end_line > file_entries[file].lines_num)
  1044.       end_line = file_entries[file].lines_num;
  1045.     for (count = start_line; count < end_line; count++)
  1046.     { if (line_cache[count - start_line].l_addr.l_paddr >= addr)
  1047.       { start_line = count - LINE_CACHE_SKIP;
  1048.     total_lines = file_entries[file].lines_num;
  1049.     while (start_line < 0 && start_file > 0)
  1050.     { total_lines += file_entries[--start_file].lines_num;
  1051.       start_line += file_entries[start_file].lines_num;
  1052.     }
  1053.     if (start_line < 0)
  1054.       start_line = 0;
  1055.     get_line_block (start_file, start_line, line_cache);
  1056.     while (total_lines < LINE_CACHE_SIZE && ++end_file < num_files)
  1057.       total_lines += file_entries[end_file].lines_num;
  1058.     if (end_file == num_files)
  1059.       end_file--;
  1060.     if (total_lines < LINE_CACHE_SIZE)
  1061.       line_cache_info.e_addr = 
  1062.         line_cache[total_lines - 1].l_addr.l_paddr;
  1063.     else
  1064.       line_cache_info.e_addr = 
  1065.         line_cache[LINE_CACHE_SIZE - 1].l_addr.l_paddr;
  1066.     line_cache_info.cached_files = 0;
  1067.     while (start_file <= end_file)
  1068.     { line_cache_info.cached_files++;
  1069.       line_cache_info.files_cached = 
  1070.            realloc (line_cache_info.files_cached, 
  1071.             line_cache_info.cached_files * sizeof (int));
  1072.       line_cache_info.files_cached[line_cache_info.cached_files - 1] =
  1073.            start_file;
  1074.       line_cache_info.begin = 
  1075.            realloc (line_cache_info.begin, 
  1076.             line_cache_info.cached_files * sizeof (word32));
  1077.       line_cache_info.begin[line_cache_info.cached_files - 1] =
  1078.            file_entries[start_file].first_addr;
  1079.       line_cache_info.end = 
  1080.            realloc (line_cache_info.end, 
  1081.             line_cache_info.cached_files * sizeof (word32));
  1082.       line_cache_info.end[line_cache_info.cached_files - 1] =
  1083.            file_entries[start_file].last_addr;
  1084.       start_file++;
  1085.     }                                                   
  1086.     line_cache_info.b_addr = line_cache[0].l_addr.l_paddr;
  1087.     return;
  1088.       }
  1089.     }
  1090.   } while (end_line < file_entries[file].lines_num);
  1091. }
  1092. /* ----------------------------------------------------------------- */
  1093. static void
  1094. fill_line_cache (word32 addr)
  1095. { int f;
  1096.   for (f = 0; f < num_files; f++)
  1097.   { if (addr >= file_entries[f].first_addr &&
  1098.     addr <= file_entries[f].last_addr  &&
  1099.     file_entries[f].lines_num)
  1100.     { do_fill (addr, f);
  1101.       return;
  1102.     }
  1103.   }
  1104. }                                                                               
  1105. /* ----------------------------------------------------------------- */
  1106. static void
  1107. lookup_file_num (word32 addr, int *file)
  1108. { int i;
  1109.   for (i = 0; i < line_cache_info.cached_files; i++)
  1110.   { if (line_cache_info.begin[i] <= addr && addr <= line_cache_info.end[i])
  1111.     { *file = line_cache_info.files_cached[i];                      
  1112.       return;
  1113.     }
  1114.   }
  1115.   *file = -1;
  1116.   return;
  1117. }
  1118. /* ----------------------------------------------------------------- */
  1119. static int
  1120. lookup_line_cache (word32 addr, int exact, int *file)
  1121. { int i;
  1122.  
  1123.   if (!line_cache_info.cached_files)
  1124.     fill_line_cache (addr);
  1125.   if (addr < line_cache_info.b_addr || addr > line_cache_info.e_addr)
  1126.     return (-1);
  1127.   for (i = 0; i < LINE_CACHE_SIZE; i++)
  1128.   { if (line_cache[i].l_addr.l_paddr == addr)
  1129.     { lookup_file_num (addr, file);                
  1130.       return (line_cache[i].l_lnno);
  1131.     }                
  1132.     if (line_cache[i].l_addr.l_paddr > addr)
  1133.     { if (exact)
  1134.     return (-1);
  1135.       else 
  1136.       { lookup_file_num (addr, file);
  1137.     return (line_cache[i].l_lnno);
  1138.       }
  1139.     }
  1140.   }
  1141.   return (-1);
  1142. }
  1143. /* ----------------------------------------------------------------- */
  1144. static word32
  1145. get_line_by_num (int file, int num, int exact)
  1146. { int start_line, end_line = 0, count;
  1147.   LINENO *l_no;
  1148.  
  1149.   l_no = (LINENO *)dos_buffer;
  1150.   do {
  1151.     start_line = end_line;                     /* Overlap last entry */
  1152.     get_line_block (file, start_line, l_no);
  1153.     end_line = start_line + (4096 / LINESZ);
  1154.     if (end_line >= file_entries[file].lines_num)
  1155.       end_line = file_entries[file].lines_num - 1;
  1156.     for (count = start_line; count <= end_line; count++)
  1157.     { if (l_no[count - start_line].l_lnno == num)
  1158.     return (l_no[count - start_line].l_addr.l_paddr);
  1159.       if (l_no[count - start_line].l_lnno > num)
  1160.       { if (exact)
  1161.       return (0xffffffff);
  1162.     else if (count > start_line)
  1163.       return (l_no[count - 1 - start_line].l_addr.l_paddr);
  1164.     else return (l_no[0].l_addr.l_paddr);
  1165.       }
  1166.     }
  1167.   } while (end_line < file_entries[file].lines_num - 1);
  1168.   if (exact)
  1169.     return (0xffffffff);
  1170.   return (l_no[end_line - start_line].l_addr.l_paddr);
  1171. }
  1172. /* ----------------------------------------------------------------- */
  1173. word32 syms_name2val(char *name)
  1174. { int idx, sign=1, i;
  1175.   word32 v = 0;
  1176.   char *cp;
  1177.  
  1178.   undefined_symbol = 0;
  1179.   idx = 0;
  1180.   sscanf(name, "%s", name);
  1181.   if (name[0] == 0)
  1182.     return 0;
  1183.   if (name[0] == '-')
  1184.   { sign = -1;
  1185.     name++;
  1186.   } else if (name[0] == '+')
  1187.     name++;
  1188.   if (isdigit(name[0]))
  1189.   { if (sign == -1)
  1190.       return -strtoul(name, 0, 0);
  1191.     return strtoul(name, 0, 0);
  1192.   }
  1193.   cp = strpbrk(name, "+-");
  1194.   if (cp)
  1195.     idx = cp-name;
  1196.   else
  1197.     idx = strlen(name);
  1198.  
  1199.   if (name[0] == '%') /* register */
  1200.   { for (i=0; regs[i].name; i++)
  1201.       if (strncmp(name, regs[i].name, idx) == 0)
  1202.       { switch (regs[i].size)
  1203.     { case 1:
  1204.         v = *(word8 *)((word8 *)(&a_tss) + regs[i].ofs);
  1205.         break;
  1206.       case 2:
  1207.         v = *(word16 *)((word8 *)(&a_tss) + regs[i].ofs);
  1208.         break;
  1209.       case 4:
  1210.         v = *(word32 *)((word8 *)(&a_tss) + regs[i].ofs);
  1211.         break;
  1212.     }
  1213.     return v + syms_name2val(name+idx);
  1214.       }
  1215.   }
  1216.  
  1217.   for (i=0; i<idx; i++)
  1218.     if (name[i] == '#')
  1219.     { int f, lnum;
  1220.       word32 l_addr;
  1221.  
  1222.       sscanf(name+i+1, "%d", &lnum);
  1223.       for (f=0; f<num_files; f++)
  1224.       { if ((strncmp(name, file_entries[f].name, i) == 0) &&
  1225.         (file_entries[f].name[i] == 0))
  1226.     { l_addr = get_line_by_num (f, lnum, 1);
  1227.       if (l_addr != 0xffffffff)
  1228.         return l_addr + syms_name2val(name+idx);
  1229.       undefined_symbol = 1;
  1230.       return 0;
  1231.     }
  1232.       }
  1233.       undefined_symbol = 1;
  1234.       return 0;
  1235.     }
  1236.  
  1237.   i = lookup_sym_byname(name, idx, 0);
  1238.   if (i == -1)
  1239.     i = lookup_sym_byname(name, idx, 1);
  1240.   if (i != -1)
  1241.     return name_cache[i].address * sign + syms_name2val(name+idx);
  1242.   undefined_symbol = 1;
  1243.   return 0;
  1244. }
  1245. /* ----------------------------------------------------------------- */
  1246. static char noname_buf[11];
  1247. /* ----------------------------------------------------------------- */
  1248. char *syms_val2name(word32 val, word32 *delta)
  1249. { int pos;
  1250.  
  1251.   if (delta)
  1252.     *delta = 0;
  1253.   if (num_syms <= 0) 
  1254.     goto noname;  
  1255.   pos = get_sym_by_addr (val);
  1256.   if (pos < 0)
  1257.     goto noname;
  1258.  
  1259.   if (delta)
  1260.     *delta = val - addr_cache[pos].address;
  1261.   return (addr_cache[pos].name);
  1262. noname:
  1263.   sprintf(noname_buf, "%#lx", val);
  1264.   return noname_buf;
  1265. }
  1266. /* ----------------------------------------------------------------- */
  1267. char *syms_val2line(word32 val, int *lineret, int exact)
  1268. { int f;
  1269.   if (val < line_cache_info.b_addr || val > line_cache_info.e_addr)
  1270.     fill_line_cache (val);
  1271.   *lineret = lookup_line_cache (val, exact, &f);
  1272.   if (*lineret == -1)
  1273.     return 0;
  1274.   return (file_entries[f].name);
  1275. }
  1276. /* ----------------------------------------------------------------- */
  1277. static void
  1278. get_lots_sym_name_by_num (SymNode *sym, word32 num)
  1279. { static word32 i = 0;
  1280.   static int used = 0, left = 4096;
  1281.   word32 offset, j, k;
  1282.   SymFileEntry entry;
  1283.                     
  1284.   if (num >= num_syms)
  1285.     return;
  1286.   if ((i == 0) || (num == 0) || (num != i + 1) || (left < 300))
  1287.   { offset = num * sizeof (SymFileEntry) + sym_header.syms_size;   
  1288.     fseek (sym_file, offset, SEEK_SET);
  1289.     fread (&entry, sizeof (SymFileEntry) , 1, sym_file);
  1290.     offset = entry.offset;
  1291.     fseek (sym_file, offset, SEEK_SET);
  1292.     fread (dos_buffer , 1 , 4096, sym_file);
  1293.     used = 0;
  1294.     left = 4096;
  1295.   }
  1296.   i = num;        
  1297.   sym->address = *(word32 *)(dos_buffer + used);
  1298.   sym->type_c  = dos_buffer[used + 4];
  1299.   for (j = used + 5, k = 0; dos_buffer[j] != '\n'; j++, k++)
  1300.      sym->name[k] = dos_buffer[j];
  1301.   sym->name[k++] = 0;
  1302.   j++;
  1303.   used = j;
  1304.   left = 4096 - used;
  1305. }
  1306. /* ----------------------------------------------------------------- */
  1307. static char wild_buf[200];
  1308. char *
  1309. syms_makewild(word32 sym_num)
  1310. { int lnum;
  1311.   char *name;
  1312.   SymNode sym;
  1313.  
  1314.   sym.name = alloca (151);  
  1315.   get_sym_name_by_num (&sym, sym_num);
  1316.   name = syms_val2line(sym.address, &lnum, 0);
  1317.   sprintf (wild_buf, "0x%08lx %c %s", sym.address, sym.type_c, sym.name);
  1318.   if (name)
  1319.     sprintf (wild_buf + strlen (wild_buf), 
  1320.          ", line %d of %s", lnum, name);
  1321.   return (wild_buf);
  1322. }         
  1323. /* ----------------------------------------------------------------- */
  1324. void
  1325. syms_get (word32 sym_num, word32 *address, char *type_c)
  1326. { SymNode sym;
  1327.  
  1328.   sym.name = alloca (151);  
  1329.   get_sym_name_by_num (&sym, sym_num);
  1330.   *address = sym.address;
  1331.   *type_c  = sym.type_c;
  1332. }
  1333. /* ----------------------------------------------------------------- */
  1334. void syms_listwild(char *pattern,
  1335.            void (*handler)(word32))
  1336. { int i;
  1337.   SymNode sym;
  1338.   sym.name = alloca (151);  
  1339.  
  1340.   for (i=0; i<num_syms; i++)
  1341.   { get_lots_sym_name_by_num (&sym, i);
  1342.     if (wild(pattern, sym.name))                
  1343.       handler (i);
  1344.   }
  1345. }                                                    
  1346. /* ----------------------------------------------------------------- */
  1347. char *get_module(int count)
  1348. { char *s;
  1349.  
  1350.   if ((count < 0) || (count == num_files))
  1351.   { undefined_symbol = 1;
  1352.     return 0;
  1353.   }
  1354.   s = strdup(file_entries[count].name);
  1355.   return s;
  1356. }
  1357. /* ----------------------------------------------------------------- */
  1358. word32 get_linenum(int filenum, int linenum)
  1359. { if ((filenum < 0) || (filenum >= num_files))
  1360.   { undefined_symbol = 1;
  1361.     return 0;
  1362.   }
  1363.   return (get_line_by_num (filenum, linenum, 0));
  1364. }
  1365.  
  1366. #endif
  1367.